﻿/**
 * 工具栏模块 - 核心模块 -- 必选
 * 实现工具栏功能，包括构建工具栏，设置工具栏按钮的事件，
 * 不要在这里包含和工具栏不相干的功能。
 */
(function(E, $){

var Consts = E.consts, toolbarList = {}, 
	toolbarLockedMsg = '提示：工具栏被锁定，请稍等...',
	Event = E.mod('Event'),
	timeoutId = 0;
	
//对外公开的对象
E.mod("Toolbar", {
	get: function(eid){
		eid = eid || E.eid;
		return toolbarList[eid];
	},
	getMessage: function(eid){
		eid = eid || E.eid;
		return toolbarList[eid].find('.jqe-message');
	},
	set: function( option ){
		MainToolbar.init( option ).setHtml( ).setEvent( );
	},
	
	//设置按钮的选中状态
	selected: function( Plugin ){
		var btn = E.getButtonByName(Plugin.name),
			button = btn.closest('.jqe-button'),
			panel = $('#panel_'+Plugin.name+', #jqe-'+Plugin.name+'-0');
			
		$('.jqe-button-hover').removeClass('jqe-button-hover');
		
		panel.is(':visible')
			? button.addClass('jqe-button-hover')
			: button.removeClass('jqe-button-hover');
	},
	
	updateState: function(){
		MainToolbar.updateState( );
	},
	
	getCurrent: function( ){
		var minTop = $(document).scrollTop(),
			jqeditors = $(".jqeditor"),
			eid = '',
			jqe,
			top = 0;
		for(var i=0, len = jqeditors.length; i<len; i++){
			jqe = jqeditors.eq(i);
			top = jqe.offset().top,
			bottom = top + jqe.height(),
			maxTop = minTop + $(window).height();
			
			// 判断编辑器是否在屏幕可视范围，编辑器上边框可见或下边框可见即可
			// 有四种情况
			if( (top >= minTop && bottom < maxTop) //1.编辑器上下两边都在可使区域
				|| ( top < minTop && bottom > minTop && bottom < maxTop ) //2.上边不在，下边在
				|| ( top >= minTop && top < maxTop && bottom > maxTop ) //3.上边在，下边不在
				|| ( top < minTop && bottom > maxTop ) //4.上边小于minTop，下边大于maxTop
			){
				eid = jqe.attr('id');
				break;
			}else{
				
			}
		}
		
		if( eid ){
			E.setEid(eid);
			return toolbarList[eid];
		}else{
			return null;
		}
	},
	
	lock: function( ){
		var toolbar = this.get();
		toolbar.children('.jqe-list').css('opacity', 0.3).bind('mousedown.lock', function(){
			E.alert( toolbarLockedMsg );
			return false;
		});
		MainToolbar.locked = 1;
	},
	
	unlock: function( ){
		var toolbar = this.get();
		toolbar.children('.jqe-list').css('opacity', 1).unbind('mousedown.lock');
		MainToolbar.locked = 0;
	},
	
	islock: function(){
		return MainToolbar.locked;
	},
	
	resetClickButton: function( ){
		MainToolbar.clickButton[E.eid] = null;
	}
});

Event.bind("oncreate", function(){
	var Toolbar = E.mod("Toolbar"),
		option = E.get('option');
		
	Toolbar.set( option );
	resizeToolbar();
	
	setTimeout(function(){
		fixedToolbarHeight();
	}, 2000);
	setTimeout(function(){
		fixedToolbarHeight();
	}, 5000);
});

// 设置工具栏外层div的高度，防止工具栏浮动时导致页面向上跳动
// 需要稍微延时几秒执行，确保在css已经加载之后
function fixedToolbarHeight(){
	var toolbars = $(".jqe-toolbar");
	
	for(var i=0, len = toolbars.length; i<len; i++){
		var toolbar = toolbars.eq(i);
		
		// 潘雪鹏 2012-02-02
		// outerHeight - 1 会比 height 更加精确一些
		toolbar.parent().height( toolbar.outerHeight() - 1 );
	}
}

function resizeToolbar(){
	var toolbars = $(".jqe-toolbar");
	
	for(var i=0, len = toolbars.length; i<len; i++){
		var toolbar = toolbars.eq(i),
			eid = toolbar.attr('eid'),
			width = toolbar.parent().width(),
			message = toolbar.find('.jqe-message'),
			left = Math.round( (width - message.width())/2 ),
			option = E.get('option', eid),
			scrollTop = $(window).scrollTop(),
			editor = $('#'+eid+' .jqe-content'),
			maxScroll = 0;
		if( Consts.IE6 ){
			width += 1;
		}else{
			width -= 2;
		}
		toolbar.width(width);
		toolbar.find('.jqe-list').width(width);
		message.css({left:left});
		
		if(eid){
			// 计算option.toolbarTop
			E.setEid( eid );
			var option = E.get('option', eid);
			if( option ){
				toolbar.removeClass( option.fixedClassName );
				
				option.toolbarTop = toolbar.offset().top;
				// log
				
			}else{
				// log 
			}
		}else{
			// log
			
		}
		if( Consts.IE6 && !scrollTop) {
			scrollTop = document.documentElement.scrollTop;
		}
		maxScroll = editor.height() + editor.offset().top;
		if(scrollTop < option.toolbarTop || scrollTop > maxScroll){
			//当工具栏超过编辑器区域最下面的边时，则还原工具栏
			toolbar.removeClass( option.fixedClassName );
			if(Consts.IE6){
				toolbar.css('top', 0);
			}
			E.log('run', '工具栏取消浮动');
		}else{
			toolbar.addClass(option.fixedClassName);
			E.log('run', '工具栏开始浮动');
			if(Consts.IE6){
				toolbar.css('top', scrollTop);
			}
		}
	}
	// 需要优化
}

//if( !$.browser.msie || $.browser.version > 6 ){
	// ie6不执行此事件
	// 特殊情况下还是需要的 2013-02-06
	$(window).bind('resize', function(){
		clearTimeout(timeoutId);
		timeoutId = setTimeout(function(){
			resizeToolbar();
		}, 300);
	});
//}
Event.bind("onafteraction", function( e ){
	var Toolbar = E.mod("Toolbar"),
		option = E.get('option');
		
	if( e.Plugin.type == 'base' ){
		Toolbar.updateState();
	}
	
	//设置按钮的选中状态
	Toolbar.selected( e.Plugin );
	
});

//内部私有对象
var MainToolbar = {
	option: null,
	
	// 记录当前点击的按钮
	clickButton: {},
	
	// 工具栏锁定
	locked: 0,
	
	//初始化
	init: function( option ){
		this.option = option;
		return this;
	},
	
	//构建工具栏
	setHtml: function( ){
		
		var option = this.option, plugin,
			toolbars = E.config('toolbars'),
			buttons = null,
			eid = option.id,
			html = [],
			Lang = E.lang(option.lang),
			editor = $("#"+eid),
			jqe_toolbar,
			name,
			title,
			a = '<a onclick="return false" tabIndex="-1" hidefocus="true" ';
		
		if( typeof option.toolbar === "string" && toolbars[ option.toolbar ] ){
			buttons = toolbars[ option.toolbar ];
		}else if( option.toolbar && typeof option.toolbar === "object" ){
			buttons = option.toolbar;
		}else{
			buttons = toolbars['default'];
		}
		
		html.push('<ul class="jqe-list jqe-'+ option.skin +'">');
		
		for(var i=0, length = buttons.length; i<length; i++){
			name = buttons[i];
			title = '';
			plugin = E.plugin(name);
			
			//如果插件不存在，丢弃
			if( !plugin){
				//记录日志
				E.log('warning', '编辑器 '+eid+' 名字为'+ name +'的插件不存在');
				continue;
			}else if( $.inArray('plugin.'+name, option.disabled) > -1){
				//记录日志
				E.log('warning', '编辑器 '+eid+' 名字为'+ name +'的插件被配置文件禁用了');
				plugin.disable();
				continue;
			}
			
			if(typeof Lang[name] == "string"){
				title = Lang[name];
			}else if(typeof Lang[name] == "object"){
				if (Lang[name].length){
					title = Lang[name][0] + Lang[name][1];
				}else{
					title = Lang[name]['title'];
				}
			}
			
			// 给插件设置title属性
			plugin.title = title;
			
			html.push('<li id="'+eid+'-'+ name +'" class="jqe-button '+ name +'"');
			
			html.push(' style="');
			if( typeof plugin.menu == Consts.typeof_function ){
				// 插件右侧需要显示下拉箭头，需要定义width属性
				
				if( plugin.icon && plugin.icon.width ){
					html.push(' width:'+(plugin.icon.width + 12)+'px;');
				}else if( typeof plugin.menu == Consts.typeof_function ){
					html.push(' width:34px;');
				}
			}else if( plugin.icon && plugin.icon.width ){
				html.push(' width:'+( plugin.icon.width )+'px;');
			}
			html.push('"');
			
			html.push('>');
			html.push('<div style="display:inline-block;" name="'+ name +'" title="'+ title +'" _title="'+ title +'">');
			//说明：
			//按钮标签，这里使用A标签
			//可以考虑使用有href熟悉的A或者img标签，使用其他如div标签在IE下会遇到问题，
			//比如，选中一些文章，然后再点击【加粗】图标，
			//在IE下编辑器编辑区域选中的文字会丢失选中状态，
			//从而导致执行失败。
			//使用img，需要浏览器加载一个图片，
			//而且当使用ctrl + f5时会导致同一个图片加载很多次的情况。
			
			//总结:使用A标签较为合适，所有点击执行命令的按钮都需要使用A标签。
			html.push(a);
			
			if(plugin.icon){
				html.push(' style="');
				if( plugin.icon.width ){
					html.push(' width:'+plugin.icon.width+'px;');
				}
				html.push('"');
			}
			
			html.push(' class="jqe-icon '+ name +'" href="jqe:'+ title+ '('+ name +')">');
			html.push('<span class="jqe-icon '+name+'"');
			
			if(plugin.icon){
				html.push(' style="');
				if( plugin.icon.width ){
					html.push(' width:'+plugin.icon.width+'px;');
				}
				html.push('"');
			}
			
			html.push('>');
			
			if(plugin.icon){
				if( plugin.icon.text ){
					html.push(plugin.icon.text);
				}
			}
			
			html.push('</span>');
			
			if(/(ForeColor|BackColor)/i.test(name) ){
				html.push('<span class="selected-color"></span>');
			}
			
			html.push('</a>');
			
			//检查插件是否有plugin.menu()方法，
			//如有则添加下拉菜单标签
			if( typeof plugin.menu == Consts.typeof_function ){
				html.push(a);
				if( plugin.menuTitle ){
					html.push(' title="'+ plugin.menuTitle +'"');
				}
				html.push(' class="jqe-button-menu" href="jqe:'+ title +'"><span></span></a>');
			}
			html.push('</div>');
			html.push('</li>');
		}
		html.push('</ul>');
		
		html.push('<textarea id="jqe-paste-text" style="position:absolute;top:-5px;width:0px;height:0px;border:none;resize:none;"></textarea>');
		html.push('<div class="jqe-message"></div>');
		
		jqe_toolbar = editor.find('.jqe-toolbar');
		if( !jqe_toolbar.size() ){
			editor.prepend('<div><div class="jqe-toolbar"></div></div>');
			jqe_toolbar = editor.find('.jqe-toolbar');
		}
		
		jqe_toolbar.html( html.join('') ).attr('eid', eid);

		toolbarList[eid] = jqe_toolbar;
		return this;
	},
	
	action: function( target, e ){
		if( target.is('.jqe-icon, .jqe-button-menu') ){
			E.action( target, e );
		}else{
			var Panel = E.mod('Panel'), Menu = E.mod('Menu');
			
			if( self.locked ){
				return false;
			}
			
			if( Menu ){
				Menu.hide();
			}
			if( Panel ){
				Panel.hide();
			}
		}
	},
	
	/*
	 * 设置工具栏事件
	 */
	setEvent: function( ){
		var self=this, option = self.option,
			eid = option.id,
			jqe_toolbar = toolbarList[eid];
			
		//说明：
		//给按钮绑定点击事件有两种方式，
		//给每个按钮绑定一个事件，
		//或者给按钮们的父节点绑定一个事件。
		//给每个按钮都绑定事件，需要绑定很多次，有些浪费，
		//因为每绑定一次事件都需要一点资源。
		//这里采用第二种，这种方式称为事件委托。
		jqe_toolbar.click(function( e ){
			// 2011-08-16 潘雪鹏
			// 不能在这里执行Panel.hide() 和 Menu.hide();
			
			self.action( $(e.target), e );
			// 终止事件冒泡
			//点击按钮以外的区域或页面的任意位置时，需要隐藏面板
			return false;
		});
		
		//2011.01.28 潘雪鹏
		//屏蔽工具栏的鼠标按下和右键点击事件
		//工具栏当中有A标签，默认在鼠标按下时会出现一个虚线边，
		//而且鼠标在图标上按下后可将链接拖动到编辑器区域或其他地方，
		//在非IE浏览器下通过设置 mousedown return false 可以解决这个问题，
		//而IE需要给A链接添加属性hidefocus="true"，
		//非IE浏览器也可以设置css a{outline:none}解决。
		
		//2011.01.29 14:17 潘雪鹏
		//设置工具栏按钮鼠标按下和松开时的视觉效果
		jqe_toolbar.bind('mousedown', function( e ){
			if(  $(e.target).is("input,textarea") ){
				return true;
			}
			if( self.locked ){return false;}
			var target = $(e.target).closest('.jqe-icon, .jqe-button-menu');
			if( target.size() ){
				target.addClass('mousedown');
				var id = target.closest(".jqe-button").attr("id").split("-");
				self.clickButton[ id[0] ] = id[1];
			}
			return false;
		}).bind('mouseup', function( e ){
			if( self.locked ){return false;}
			var target = $(e.target).closest('.jqe-icon, .jqe-button-menu');
			if( target.size() ){
				target.removeClass('mousedown');
			}
			return false;
		})/*.bind("click", function( e ){
		
			if( self.locked ){return false;}
			var target = $(e.target).closest('.jqe-button');
			if( target.size() ){
				target.addClass('jqe-button-clicked');
				var id = target.attr("id");
				E.log("run", "记录点击按钮"+ id);
			}
			return false;
		
		})*/;
		
		// 2011-08-16 潘雪鹏
		// 此处遇到诡异问题，jqe_toolbar.find('。jqe-button')
		// 每次鼠标移到按钮都会触发3次事件，mouseover mousemout mouseover
		// 后改为jqe_toolbar.find('div[name]')，则正常
		jqe_toolbar.find('div[name]').bind('mouseover', function( e ){
			var target = $(this),
				button = target.parent(),
				id = button.attr("id").split("-");
				
			if( self.locked
				|| button.hasClass('disabled')
				|| target.hasClass('disabled')
				|| self.clickButton[ id[0] ] === id[1]
			){
				return false;
			}
			
			if( !button.hasClass('jqe-button-hover') ){
				// 2011-08-23 21:31 潘雪鹏
				// 在mouseover触发显示下拉菜单，过于灵敏了，反而感觉不爽，顾取消
				// E.hidePanel();
				button.addClass('jqe-button-hover');
			}
			
			self.clickButton[ id[0] ] = null;
			return false;
		}).bind('mouseout', function( e ){
			var target = $(this),
				button = target.parent(),
				id = button.attr("id").split("-");
			if( self.locked
				|| target.hasClass('disabled')
				
				// 当mouseout移出地按钮是刚刚点击的按钮时，
				// 不执行button.removeClass('jqe-button-hover');
				|| self.clickButton[ id[0] ] === id[1]
			){
				return false;
			}
			
			if( button.hasClass('jqe-button-hover') ){
				button.removeClass('jqe-button-hover');
			}
			return false;
		});
		
		//方便开放阶段调试
		if( !E.debug ){
			jqe_toolbar.bind('contextmenu', Consts.returnFalse);
		}
		return this;
	},
	
	/**
	 * 检测光标所在位置是否执行过当前命令，
	 * 在点击内容区域、工具栏按钮以及和内容keyup时执行
	 */
	updateState: function( ){
		var self=this, eid = E.eid, dom = E.get('document'),
			cmds = Consts.baseCmds, cmd, state=false;
		
		for (var i=0, len = cmds.length; i<len; i++){
			cmd=cmds[i];
			try{
				state = dom.queryCommandState(cmd);
			}catch(e){
				state=false;
			}
			
			if(state){
				$("#"+eid+"-"+cmd).addClass("jqe-button-checked");
			}else{
				$("#"+eid+"-"+cmd).removeClass("jqe-button-checked");
			}
        }
		return self;
    }
}

})(jQEditor, jQuery);